package com.key.win.business.chat.service.impl;

import com.key.win.base.auth.AuthenticationUtil;
import com.key.win.base.auth.detail.Authentication;
import com.key.win.base.util.SingleSoldierConstantUtils;
import com.key.win.business.chat.eums.ImMessageContentTypeEnum;
import com.key.win.business.chat.eums.ImMessageTargetEnum;
import com.key.win.business.chat.eums.ImMessageTypeEnum;
import com.key.win.business.chat.model.ImMessage;
import com.key.win.business.chat.service.ImChatService;
import com.key.win.business.chat.service.ImMessageService;
import com.key.win.business.chat.session.ChatSession;
import com.key.win.business.chat.session.ChatSessionUtil;
import com.key.win.business.chat.vo.*;
import com.key.win.common.websocket.manager.WebSocketManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

@Component
public class ImChatServiceImpl implements ImChatService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WebSocketManager webSocketManager;

    @Autowired
    private ImMessageService imMessageService;

    @Override
    public void friendChat(ImMessageChatFriendInVo imMessageTokenVo) {
        ChatSession chatSession = ChatSessionUtil.getChatSession(imMessageTokenVo);
        sendMessageToFriend(imMessageTokenVo, chatSession);
    }

    @Override
    public void groupChat(ImMessageChatGroupInVo imMessageChatGroupInVo) {
        ChatSession chatSession = ChatSessionUtil.getChatSession(imMessageChatGroupInVo);
        sendMessageToGroup(imMessageChatGroupInVo, chatSession);

    }

    public List<ChatSession> getAllChatSession() throws IOException {
        return ChatSessionUtil.getAllChatSession();
    }

    @Override
    public void addChat(ImMessageTargetEnum type, String id) {
        logger.info("type：{}", type);
        if (type == ImMessageTargetEnum.FRIEND) {
            ChatSessionUtil.addUserToFriendChatSession(id, AuthenticationUtil.getToken());
        } else if (type == ImMessageTargetEnum.GROUP) {
            ChatSessionUtil.addUserToGroupChatSession(id, AuthenticationUtil.getToken());
        } else {
            logger.error("type is null !!");
        }
    }

    @Override
    public void sendMessageToChat(ImMessageChatVo imMessageChatVo) {
        logger.info("type：{}", imMessageChatVo.getType());
        if (imMessageChatVo.getType() == ImMessageTargetEnum.FRIEND) {
            ChatSession chatSession = ChatSessionUtil.getChatSession(SingleSoldierConstantUtils.getRedisFriendSessionKey(imMessageChatVo.getChatSessionId()));
            sendMessageToFriend(imMessageChatVo, chatSession);
        } else if (imMessageChatVo.getType() == ImMessageTargetEnum.GROUP) {
            ChatSession chatSession = ChatSessionUtil.getChatSession(SingleSoldierConstantUtils.getRedisGroupSessionKey(imMessageChatVo.getChatSessionId()));
            sendMessageToGroup(imMessageChatVo, chatSession);
        } else {
            logger.error("type is null !!");
        }
    }

    private void sendMessageToGroup(ImMessageChatBaseInVo imMessageChatVo, ChatSession chatSession) {
        Set<String> userIds = chatSession.getUserIds();
        AtomicReference<String> imMessageId = new AtomicReference<>(null);
        if (!CollectionUtils.isEmpty(userIds)) {
            userIds.forEach(userId -> {
                Authentication authenticationToRedis = AuthenticationUtil.getOnLineUserByUserId(userId);
                boolean status = false;
                String groupId = new String(ChatSessionUtil.decoder.decode(chatSession.getSessionId().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
                if (authenticationToRedis != null) {
                    status = true;
                    if (!userId.equals(AuthenticationUtil.getUserId())) {
                        ImMessageChatGroupOutVo imMessageTokenVo = new ImMessageChatGroupOutVo();
                        imMessageTokenVo.setGroupId(groupId);
                        imMessageTokenVo.setMessage(imMessageChatVo.getMessage());
                        imMessageTokenVo.setTimestamp(imMessageChatVo.getTimestamp());
                        imMessageTokenVo.setContentType(ImMessageContentTypeEnum.getImMessageContentTypeEnum(imMessageChatVo.getContentType()).name());
                        webSocketManager.sendMessageByUserName(authenticationToRedis.getUserName(), imMessageTokenVo);
                    }
                }
                saveImMessage(imMessageChatVo, imMessageId, userId, status, groupId, ImMessageTypeEnum.GROUP_NORMAL, ImMessageTargetEnum.GROUP);
            });
        }

    }

    private void saveImMessage(ImMessageChatBaseVo imMessageChatVo, AtomicReference<String> imMessageId, String toUserId, boolean status, String targetId, ImMessageTypeEnum type, ImMessageTargetEnum target) {
        ImMessage imMessage = new ImMessage();
        imMessage.setId(imMessageId.get());
        imMessage.setType(type);
        imMessage.setTargetId(targetId);
        imMessage.setTarget(target);
        imMessage.setFromUserId(AuthenticationUtil.getUserId());
        imMessage.setContent(imMessageChatVo.getMessage());
        imMessage.setContentType(ImMessageContentTypeEnum.getImMessageContentTypeEnum(imMessageChatVo.getContentType()));
        imMessageService.addMessage(imMessage, status, toUserId);
        imMessageId.set(imMessage.getId());
    }

    private void sendMessageToFriend(ImMessageChatBaseVo imMessageChatVo, ChatSession chatSession) {
        Set<String> userIds = chatSession.getUserIds();
        AtomicReference<String> imMessageId = new AtomicReference<>(null);
        if (!CollectionUtils.isEmpty(userIds)) {
            userIds.forEach(userId -> {
                if (userId.equals(AuthenticationUtil.getUserId())) {
                    return;
                }
                boolean status = false;
                Authentication authenticationToRedis = AuthenticationUtil.getOnLineUserByUserId(userId);
                if (authenticationToRedis != null) {
                    status = true;
                    ImMessageChatFriendOutVo imMessageTokenVo = new ImMessageChatFriendOutVo();
                    ImUserVo imUserVo = new ImUserVo();
                    imUserVo.setId(authenticationToRedis.getId());
                    imUserVo.setNickName(authenticationToRedis.getNickName());
                    imMessageTokenVo.setToUser(imUserVo);
                    imMessageTokenVo.setMessage(imMessageChatVo.getMessage());
                    imMessageTokenVo.setTimestamp(imMessageChatVo.getTimestamp());
                    imMessageTokenVo.setContentType(ImMessageContentTypeEnum.getImMessageContentTypeEnum(imMessageChatVo.getContentType()).name());
                    webSocketManager.sendMessageByUserName(authenticationToRedis.getUserName(), imMessageTokenVo);
                }
                saveImMessage(imMessageChatVo, imMessageId, userId, status, userId, ImMessageTypeEnum.FRIEND_NORMAL, ImMessageTargetEnum.FRIEND);
            });
        }
    }
}
